package com.rt.cloud.auth.config;

import com.rt.cloud.auth.config.exception.UserOAuth2WebResponseExceptionTranslator;
import com.rt.cloud.auth.config.login.UinteRequestValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private MyUserDetailServiceImpl myUserDetailService;

    @Autowired
    private TokenStore jwtTokenStore;

    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Autowired
    private TokenEnhancer jwtTokenEnhancer;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserOAuth2WebResponseExceptionTranslator userOAuth2WebResponseExceptionTranslator;

    @Autowired
    private UinteRequestValidator uinteRequestValidator;

    //令牌端点的安全配置
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()");
        // 认证后可访问 /oauth/check_token , 默认拒绝访问
        security.checkTokenAccess("isAuthenticated()");
        //主要是让/oauth/token支持client_id以及client_secret作登录认证
        security.allowFormAuthenticationForClients();
    }

    public ClientDetailsService jdbcClientDetailsService(){
        return new JdbcClientDetailsService(dataSource);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(jdbcClientDetailsService());
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // token信息扩展 // 自定义token生成方式
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> enhancerList = new ArrayList<>();
        enhancerList.add(jwtTokenEnhancer);
        enhancerList.add(jwtAccessTokenConverter);
        enhancerChain.setTokenEnhancers(enhancerList);

        //
        endpoints.authenticationManager(authenticationManager)//密码模式设置认证管理器
                .userDetailsService(myUserDetailService)// 刷新令牌获取新令牌时需要
                .tokenStore(jwtTokenStore)//token管理策略
                .accessTokenConverter(jwtAccessTokenConverter)//JWT令牌
                .tokenEnhancer(enhancerChain)//token信息扩展
                .exceptionTranslator(userOAuth2WebResponseExceptionTranslator) // 页面正常显示登录失败信息； 自定义错误接口实现类 处理 ExceptionTranslationFilter 抛出的异常
                //.requestValidator(uinteRequestValidator) // https://blog.csdn.net/likemiddle/article/details/90770346
        ;

        /* 在数据库中设置token有效时间
        //  设置token有效时间
        endpoints.authenticationManager(authenticationManager)//密码模式设置认证管理器
                .userDetailsService(myUserDetailService)// 刷新令牌获取新令牌时需要
                .tokenStore(jwtTokenStore)//token管理策略
                .accessTokenConverter(jwtAccessTokenConverter)//JWT令牌
        ;
        endpoints.tokenServices(defaultTokenServices());
        // endpoints.exceptionTranslator(loggingExceptionTranslator());
        endpoints.exceptionTranslator(webResponseExceptionTranslator);*/

    }

    /*
    // 设置token有效时间
    @Bean
    @Primary
    public DefaultTokenServices defaultTokenServices(){
        // token信息扩展
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> enhancerList = new ArrayList<>();
        enhancerList.add(jwtTokenEnhancer);
        enhancerList.add(jwtAccessTokenConverter);
        enhancerChain.setTokenEnhancers(enhancerList);

        DefaultTokenServices services=new DefaultTokenServices();
        services.setAuthenticationManager(authenticationManager);
        services.setSupportRefreshToken(true);
        services.setReuseRefreshToken(true);
        services.setTokenEnhancer(enhancerChain);
        services.setAccessTokenValiditySeconds(10);//设置20秒过期
        services.setRefreshTokenValiditySeconds(-1);//设置刷新token的过期时间
        services.setTokenStore(jwtTokenStore);
        // services.setClientDetailsService(clientDetailsService());
        return services;
    }

    public ClientDetailsService clientDetailsService(){
        return new ClientDetailsService() {
            @Override
            public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
                return null;
            }
        } ;
    }

    */
    /**
     * 异常堆栈信息
     * error="invalid_token", error_description="Token has expired"
     * @return
     *//*

    @Bean
    public WebResponseExceptionTranslator loggingExceptionTranslator() {
        return new DefaultWebResponseExceptionTranslator() {

            @Override
            public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
                //异常堆栈信息输出
                System.out.println("异常堆栈信息");
                e.printStackTrace();
                return super.translate(e);

                */
/*if (e instanceof OAuth2Exception) {
                    // int code = UserCode.OAUTH_ERROR;
                    // String message = i18nHelper.getMessage(code);
                    return ResponseEntity.ok(new Result());
                }
                throw e;*//*

            }
        };
    }
*/






}
